package 蚂蚁课堂;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.StampedLock;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class StampedLockDemo1 {


    //创建StampedLock锁
    private static final StampedLock lock=new StampedLock();

    private static List<Long> list=new ArrayList<>();

    //读取操作的计数器
    private static int readNum=0;
    //写入操作的计数器
    private static int writeNum=0;

    public static void main(String[] args) {
        //创建固定大小的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(1000);
        Runnable read=()->{
          for (;;){
              read();
          }
        };

        Runnable write=()->{
            for (;;){
                write();
            }
        };
        //执行995个线程的读操作
        for (int i=0;i<995;i++){
            executorService.submit(read);
        }
        //执行一次写操作
        executorService.submit(write);
    }
    /**
     * 悲观读：悲观读就是读取操作抢占到了锁，同时此时没有写操作。
     * StampedLock的悲观读就和ReentrantReadWriteLock的悲观读一样的
     */
    private static void read(){
        long stamp=-1;
        try {
            stamp= lock.readLock();
            String collect = list.parallelStream().map(String::valueOf).collect(Collectors.joining("~"));
            readNum++;
            System.out.println("读取数据："+readNum);

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlockRead(stamp);
        }
    }

    /**
     *悲观写：StampedLock的悲观写和ReentrantReadWriteLock的悲观写一样的
     */
    private static void write(){
        long stamp =-1;
        try {
            stamp =lock.writeLock();
            long l = System.currentTimeMillis();
            list.add(l);
            writeNum++;
            System.out.println("写入数据执行~~~~~~~~~"+writeNum);

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlockWrite(stamp);
        }

    }
}
